#后台管理
from .import admin_blue
from flask import request,render_template,session,current_app,redirect,url_for,g,abort,jsonify
from info.models import User,News,Category
from info.utils.comment import user_login_data
import time,datetime
from info import constants,response_code,db
from info.utils.file_storage import upload_file


#新闻分类
@admin_blue.route('/news_type', methods=['GET','POST'])
def news_type():
    """新闻分类管理"""

    # 渲染新闻分类界面
    if request.method == 'GET':
        # 查询新闻分类数据
        categories = []
        try:
            categories = Category.query.all()
            categories.pop(0)
        except Exception as e:
            current_app.logger.error(e)
            abort(404)

        context = {
            'categories':categories
        }

        return render_template('admin/news_type.html',context=context)

    # 修改和增加新闻分类
    if request.method == 'POST':
        # 1接受参数
        cname = request.json.get('name')
        cid = request.json.get('id')

        # 2校验参数
        if not cname:
            return jsonify(errno=response_code.RET.PARAMERR, errmsg='缺少参数')

        # 3根据是否有cid判断是增加分类还是修改分类
        if cid:
            # 修改分类
            try:
                category = Category.query.get(cid)
            except Exception as e:
                current_app.logger.error(e)
                return jsonify(errno=response_code.RET.DBERR, errmsg='查询分类失败')
            if not category:
                return jsonify(errno=response_code.RET.NODATA, errmsg='分类不存在')
            # 修改分类名字
            category.name = cname
        else:
            # 增加分类
            category = Category()
            category.name = cname
            db.session.add(category)

        # 4同步到数据库
        try:
            db.session.commit()
        except Exception as e:
            db.session.rollback()
            current_app.logger.error(e)
            return jsonify(errno=response_code.RET.DBERR, errmsg='保存分类数据失败')
        #5
        return jsonify(errno=response_code.RET.OK, errmsg='OK')

#新闻版式编辑点击编辑详情
@admin_blue.route('/news_edit_detail/<int:news_id>',methods=['POST','GET'])
def news_edit_detail(news_id):
    if request.method == 'GET':
        #直接查询要编辑的新闻
        news = None
        try:
            news = News.query.get(news_id)
        except Exception as e:
            current_app.logger.error(e)
            abort(404)
        if not news:
            abort(404)
        #直接查询分类
        categories = []
        try:
            categories = Category.query.all()
            categories.pop(0)
        except Exception as e:
            current_app.logger.error(e)
            abort(404)
        #构造渲染数据
        context = {
            'news':news.to_dict(),
            'categories':categories

        }
        return render_template('admin/news_edit_detail.html',context = context)
     #2新闻版式编辑详情
    if request.method == 'POST':
        #2.1接受参数
        # news_id = request.form.get('news_id') 前段已经有了这个值所以不用
        title = request.form.get('title')
        digest = request.form.get('digest')
        content = request.form.get('content')
        index_image = request.files.get('index_image')
        category_id = request.form.get('category_id')
        #2.2校验参数
        if not all([news_id,title,digest,content,category_id]):
            return jsonify(errno=response_code.RET.PARAMERR, errmsg='缺少参数')
        #2.3查询要编辑的新闻
        try:
            news = News.query.get(news_id)
        except Exception as e:
            current_app.logger.error(e)
            return jsonify(errno=response_code.RET.PARAMERR, errmsg='查询新闻数据失败')
        if not news:
            return jsonify(errno=response_code.RET.PARAMERR, errmsg='新闻数据不存在')
        #2.4读取和上传图片
        if index_image:
            try:
                index_image = index_image.read()
            except Exception as e:
                return jsonify(errno=response_code.RET.PARAMERR, errmsg='读取新闻数据失败')
        #2.5上传到7牛
            try:
                key = upload_file(index_image)
            except Exception as e:
                current_app.logger.error(e)
                return jsonify(errno=response_code.RET.THIRDERR, errmsg='上传失败')

            news.index_image_url = constants.QINIU_DOMIN_PREFIX + key

        #2.6保存数据并同步到数据库
        news.title = title
        news.digest = digest
        news.content = content
        news.category_id = category_id

        try:
            db.session.commit()
        except Exception as e:
            db.session.rollback()
            current_app.logger.error(e)
            return jsonify(errno=response_code.RET.DBERR, errmsg='保存数据失败')

        # 2.7 响应结果
        return jsonify(errno=response_code.RET.OK, errmsg='OK')
#新闻板式编辑
@admin_blue.route('/news_edit')
def news_edit():
    #1接受参数
    page = request.args.get('p',1)
    keyword = request.args.get('keyword')

    #2校验参数
    try:
        page = int(page)
    except Exception as e:
        current_app.logger.error(e)
        page = '1'

    #3分页查询
    news_list = []
    total_page = 1
    current_page = 1
    try:
        if keyword:
            paginate = News.query.filter(News.title.contains(keyword),News.status==0).order_by(News.create_time.desc()).paginate(page,constants.ADMIN_NEWS_PAGE_MAX_COUNT,False)
        else:
            paginate = News.query.filter(News.status == 0).order_by(News.create_time.desc()).paginate(page,constants.ADMIN_NEWS_PAGE_MAX_COUNT,False)


            news_list = paginate.items
            total_page = paginate.pages
            current_page = paginate.page
    except Exception as e:
        current_app.logger.error(e)
        abort(404)

    #构造渲染数据
    news_dict_list = []
    for news in news_list:
        news_dict_list.append(news.to_review_dict())

    context = {
        'news_list':news_dict_list,
        'total_page':total_page,
        'current_page':current_page
    }

    # 5.响应结果
    return render_template('admin/news_edit.html', context=context)
# 新闻审核
@admin_blue.route('/news_review_action',methods=['POST'])
def news_review_action():
    #1接受参数
    news_id = request.json.get('news_id')
    action = request.json.get('action')
    #2校验参数
    if not all([news_id,action]):
        return jsonify(errno=response_code.RET.PARAMERR, errmsg='缺少参数')
    if action not in ['accept','reject']:
        return jsonify(errno=response_code.RET.PARAMERR, errmsg='参数错误')
    #3查询待审核的新闻是否存在
    try:
        news = News.query.get(news_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=response_code.RET.DBERR, errmsg='查询新闻数据失败')

    if not news:
        return jsonify(errno=response_code.RET.NODATA, errmsg='新闻数据不存在')

    #4实现逻辑审核
    if action =='accept':
        #通过
        news.status = 0
    else:
        #拒觉通过
        news.status = -1
        #补充拒绝原因
        reason = request.json.get('reason')
        if not reason:
            return jsonify(errno=response_code.RET.PARAMERR, errmsg='请填写拒绝理由')
        news.reason = reason
    #5同步到数据库
    try:
        db.session.commit()
    except Exception as e:
        db.session.rollback()
        current_app.logger.error(e)
        return jsonify(errno=response_code.RET.DBERR, errmsg='保存数据失败')
    #响应最终
    return jsonify(errno=response_code.RET.OK, errmsg='Ok ')
# 待审核新闻详情
@admin_blue.route('/news_review_detail/<int:news_id>')
def news_review_detail(news_id):
    #1查询除要审核的新闻的详情  通过数据库查询实现的搜索
    news = None
    try:
        news = News.query.get(news_id)
    except Exception as e:
        current_app.logger.error(e)
        abort(404)
    if not news:
        abort(404)
    #2构造渲染数据
    context = {
        'news':news.to_dict()
    }
    return render_template('admin/news_review_detail.html',context = context)

#后台新闻审核列
@admin_blue.route('/news_review')
def news_review():
    #1接收参数
    page = request.args.get('p','1')
    keyword = request.args.get('keyword')
    #2校验参数
    try:
        page = int(page)
    except Exception as e:
        current_app.logger.error(e)
        page='1'
    #3分页查询
    news_list = []
    total_page = 1
    current_page = 1
    try:  #查询搜索框，需要获取keyword 字符串
        if keyword:
            paginate = News.query.filter(News.title.contains(keyword),News.status !=0).order_by(News.create_time.desc()).paginate(page,constants.ADMIN_NEWS_PAGE_MAX_COUNT,False)
        else:
            paginate = News.query.filter(News.status != 0).order_by(News.create_time.desc()).paginate(page,constants.ADMIN_NEWS_PAGE_MAX_COUNT,False)

        news_list = paginate.items
        total_page = paginate.pages
        current_page = paginate.page
    except Exception as e:
        current_app.logger.error(e)
        abort(404)
    #4构造渲染数据
    news_dict_list = []
    for news in news_list:
        news_dict_list.append(news.to_review_dict())

    context = {
        'news_list':news_dict_list,
        'total_page':total_page,
        'current_page':current_page
    }
    #5响应结果
    return  render_template('admin/news_review.html',context=context)

#用户列表
@admin_blue.route('/user_list')
def user_list():
    #查询用户列表 管理员除外
    #1接收参数
    page = request.args.get('p','1')
    #2校验参数
    try:
        page = int(page)
    except Exception as e:
        current_app.logger.error(e)
        page ='1'
    #3分页查询用户列表，管理员除外
    users=[]
    total_page = 1
    current_page = 1
    try:
        paginate = User.query.filter(User.is_admin==False).paginate(page,constants.ADMIN_USER_PAGE_MAX_COUNT,False)
        users = paginate.items
        total_page = paginate.pages
        current_page = paginate.page
    except Exception as e:
        current_app.logger.error(e)
        abort(404)
    #列表内格式化了所以要用字典包一下
    user_dict_list = []
    for user in users:
        user_dict_list.append(user.to_admin_dict())

    #构造渲染数据
    context = {
        'users':user_dict_list,
        'total_page':total_page,
        'current_page':current_page
    }

    return render_template('admin/user_list.html',context = context )
#用户统计
@admin_blue.route('/user_count')
def user_count():
    #用户总数
    total_count = 0
    try:
        total_count = User.query.filter(User.is_admin == False).count()
    except Exception as e:
        current_app.logger.error(e)
    #月新增用户
    month_count = 0
    #计算每月开始时间 比如2.18-06-01 00：00：00
    t = time.localtime()
    #计算每月开始时间字符  日期写死开始  年       月
    month_begin = '%d-%02d-01'%(t.tm_year,t.tm_mon)
    #计算每月开始时间对象  字符串拼接后 大写Y 2018 小写y 18
    month_begin_date = datetime.datetime.strptime(month_begin,'%Y-%m-%d')
    try:
        month_count = User.query.filter(User.is_admin ==False,User.create_time>month_begin_date).count()
    except Exception as e:
        current_app.logger.error(e)

    #日新增用户
    day_count = 0
    #计算当天开始的时间
    t = time.localtime()
    #获取今天的日期 没有写死
    day_begin = '%d-%02d-%02d'%(t.tm_year,t.tm_mon,t.tm_mday)
    day_begin_date = datetime.datetime.strptime(day_begin,'%Y-%m-%d')
    try:
        day_count = User.query.filter(User.is_admin==False,User.create_time>day_begin_date).count()
    except Exception as e:
        current_app.logger.error(e)

    #每日的用户登录活跃量
    #x轴的时间节点
    active_date = []
    #y轴的用户节点
    active_count = []
    #查询今天开始的时间 06月04 00：00：00
    #获取当前开始的时间字符串
    today_begin = '%d-%02d-%02d'%(t.tm_year,t.tm_mon,t.tm_mday)
    #获取当前开始的时间对象
    today_begin_date = datetime.datetime.strptime(today_begin,'%Y-%m-%d')
    #循环遍历
    for i in range(0,15):
        #计算一天的开始
        begin_date = today_begin_date -datetime.timedelta(days=i)
        #计算一天的结束
        end_date =today_begin_date - datetime.timedelta(days=(i-1))
        #将x轴对象的开始时间记录
        # strptime：将时间对应的字符串转换成时间对象
        # strftime:将时间对象转换成时间字符串
        active_date.append(datetime.datetime.strftime(begin_date,'%Y-%m-%d'))
        #查询当前的用户登录量
        try:
            count = User.query.filter(User.is_admin == False, User.last_login >= begin_date,
                                      User.last_login < end_date).count()
            active_count.append(count)
        except Exception as e:
            current_app.logger.error(e)
    #反转列表 保证时间线从左到右递增，千万不能用变量取接收，reverse 返回值是NOne
    active_date.reverse()
    active_count.reverse()

    context = {
        'total_count':total_count,
        'month_count' :month_count,
        'day_count':day_count,
        'active_date':active_date,
        'active_count':active_count

    }

    return render_template('admin/user_count.html',context=context)
#主页
@admin_blue.route('/')
@user_login_data
def admin_index():
    #获取登录用户信息
    user = g.user
    if not user:
        return redirect(url_for('admin.admin_login'))
    #构造渲染数据
    context = {
        'user':user.to_dict()
    }
    #渲染魔板
    return render_template('admin/index.html',context=context)

#登陆
@admin_blue.route('/login',methods=['GET','POST'])
def admin_login():
    #1get提供登录页面
    if request.method == 'GET':
        #获取登录用户信息。如果已经邓丽直接进入主页 判断是不是管理员（已经登录用户直接进入管理页面）
        user_id = session.get('user_id',None)
        is_admin = session.get('is_admin',False)
        if user_id and is_admin:
            return redirect(url_for('admin.admin_index'))
        return render_template('admin/login.html')

    #POST实现登陆的后端业务逻辑
    if request.method == 'POST':
        #1获取参数
        username = request.form.get('username')
        password = request.form.get('password')
        #2校验参数
        if not all([username,password]):
            return render_template('admin/login.html',errmsg='缺少参数')
        #3查询当前要登陆的用户是否存在
        try:
            user = User.query.filter(User.nick_name == username).first()
        except Exception as e:
            current_app.logger.error(e)
            return render_template('admin/login.html', errmsg='查询用户数据失败')
        if not user:
            return render_template('admin/login.html', errmsg='用户名或者密码错误')
        #4对比当前要登陆的用户的密码
        if not user.check_passowrd(password):
            return render_template('admin/login.html', errmsg='用户名或者密码错误')
        #5将状态保持信息写入session
        session['user_id'] = user.id
        session['nick_name'] = user.nick_name
        session['mobile'] = user.mobile
        session['is_admin'] = user.is_admin
        #6相应登陆结果
        return redirect(url_for('admin.admin_index'))

